package dao

import (
	"encoding/json"
	"fmt"
	"log"
	"order_srv/basic/config"

	"order_srv/handler/models"
	"time"
)

// 订单状态常量
const (
	OrderStatusPending   int8 = 1 // 待接单
	OrderStatusWaiting   int8 = 2 // 待上车
	OrderStatusOngoing   int8 = 3 // 行驶中
	OrderStatusUnpaid    int8 = 4 // 待支付
	OrderStatusCompleted int8 = 5 // 已完成
	OrderStatusCancelled int8 = 6 // 已取消
	OrderStatusRefunded  int8 = 7 // 已退款
)

// 记录轨迹点 - 冷热分层存储
func RecordTrajectoryPoint(orderId uint32, lat, lng float64, pointType int8) error {
	now := time.Now()
	trajectory := &models.Trajectory{
		OrderId:   orderId,   // 订单id
		Point:     pointType, // 1-途经点 2-上车点 3-下车点
		Latitude:  lat,       // 纬度
		Longitude: lng,       // 经度
		CreateAt:  now,       // 创建时间
		UpdateAt:  now,       // 更新时间
	}

	// 1. 热数据存储到Redis（最近24小时的数据）
	redisKey := fmt.Sprintf("trajectory:hot:%d", orderId)
	trajData, err := json.Marshal(trajectory)
	if err != nil {
		log.Printf("序列化轨迹数据失败: %v", err)
	} else {
		// 使用Redis的List数据结构，按时间顺序存储
		config.Rdb.LPush(config.Ctx, redisKey, trajData)
		// 设置过期时间为24小时
		config.Rdb.Expire(config.Ctx, redisKey, 24*time.Hour)
	}

	// 2. 冷数据存储到MySQL（适用于所有数据，包括热点数据的持久化）
	tx := config.DB.Begin()
	if tx.Error != nil {
		return fmt.Errorf("开始事务失败: %w", tx.Error)
	}

	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := tx.Create(trajectory).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("记录轨迹失败: %w", err)
	}

	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("提交事务失败: %w", err)
	}

	return nil
}

// 查询轨迹点 - 优先从Redis获取热数据，没有则从MySQL获取
func GetTrajectoryPoints(orderId uint32) ([]*models.Trajectory, error) {
	var trajectories []*models.Trajectory

	// 1. 尝试从Redis获取热数据
	redisKey := fmt.Sprintf("trajectory:hot:%d", orderId)
	redisData, err := config.Rdb.LRange(config.Ctx, redisKey, 0, -1).Result()

	if err == nil && len(redisData) > 0 {
		// 从Redis解析数据
		for _, data := range redisData {
			var traj models.Trajectory
			if err := json.Unmarshal([]byte(data), &traj); err != nil {
				log.Printf("解析Redis轨迹数据失败: %v", err)
				continue
			}
			trajectories = append(trajectories, &traj)
		}
		return trajectories, nil
	}

	// 2. Redis没有数据，从MySQL获取
	var t models.Trajectory
	t.OrderId = orderId
	list, err := t.GetListByOrderId()
	if err != nil {
		return nil, fmt.Errorf("从MySQL查询轨迹失败: %w", err)
	}

	// 转换切片类型
	for i := range list {
		trajectories = append(trajectories, &list[i])
	}

	return trajectories, nil
}

// 获取状态描述
func GetStatusDescription(status int8) string {
	statusMap := map[int8]string{
		OrderStatusPending:   "待接单",
		OrderStatusWaiting:   "待上车",
		OrderStatusOngoing:   "行驶中",
		OrderStatusUnpaid:    "待支付",
		OrderStatusCompleted: "已完成",
		OrderStatusCancelled: "已取消",
		OrderStatusRefunded:  "已退款",
	}

	if desc, exists := statusMap[status]; exists {
		return desc
	}

	return "未知状态"
}
